package com.baidu.fsg.uid.config;

import com.baidu.fsg.uid.IdMappingService;
import com.baidu.fsg.uid.buffer.RingBuffer;
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.baidu.fsg.uid.impl.IdMappingServiceImpl;
import com.baidu.fsg.uid.worker.DisposableWorkerIdAssigner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className UidConfig
 * @description TODO
 * @site 
 * @company 
 * @create 2020-07-12 11:16
 */
@Configuration
@Slf4j
public class CacheUidConfiguration {
    public static IdMappingService idMappingService;
    @Bean
    public IdMappingService idMappingService(){
        idMappingService = new IdMappingServiceImpl();
        return idMappingService;
    }

    @Bean
    public DisposableWorkerIdAssigner disposableWorkerIdAssigner(){
        return new DisposableWorkerIdAssigner();
    }

    @Bean
    @Primary
    public CachedUidGenerator cachedUidGenerator(@Autowired  DisposableWorkerIdAssigner disposableWorkerIdAssigner){
        CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
        cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
        // RingBuffer size扩容参数, 可提高UID生成的吞吐量. 默认:3， 原bufferSize=8192, 扩容后bufferSize= 8192 << 3 = 65536
        cachedUidGenerator.setBoostPower(3);
        //指定何时向RingBuffer中填充UID, 取值为百分比(0, 100), 默认为50
        //举例: bufferSize=1024, paddingFactor=50 -> threshold=1024 * 50 / 100 = 512.
        //当环上可用UID数量 < 512时, 将自动对RingBuffer进行填充补全
        cachedUidGenerator.setPaddingFactor(RingBuffer.DEFAULT_PADDING_PERCENT);
        //另外一种RingBuffer填充时机, 在Schedule线程中, 周期性检查填充
        //默认:不配置此项, 即不实用Schedule线程. 如需使用, 请指定Schedule线程时间间隔, 单位:秒
        cachedUidGenerator.setScheduleInterval(60);
        //拒绝策略: 当环已空, 无法继续获取时
        //默认无需指定, 将记录日志, 并抛出UidGenerateException异常. 如有特殊需求, 请实现RejectedTakeBufferHandler接口(支持Lambda表达式)
        cachedUidGenerator.setRejectedTakeBufferHandler((ringBuffer)->{
            log.warn("Rejected take buffer. {}", ringBuffer);
            throw new RuntimeException("Rejected take buffer. " + ringBuffer);
        });
        //拒绝策略: 当环已满, 无法继续填充时
        //默认无需指定, 将丢弃Put操作, 仅日志记录. 如有特殊需求, 请实现RejectedPutBufferHandler接口(支持Lambda表达式)
        cachedUidGenerator.setRejectedPutBufferHandler((ringBuffer,uid)->{
            log.warn("Rejected putting buffer for uid:{}. {}", uid, ringBuffer);
        });
        return cachedUidGenerator;
    }
}
